#include "CellType.h"

#include "CatanClassContractException.h"

namespace catan
{

/*static*/ std::vector<CellType::Enum_CellType> CellType::vectorOfPossibleEnumValues;
/*static*/ std::vector<CellType::Enum_CellType> CellType::vectorOfLandEnumValues;
/*static*/ std::vector<CellType::Enum_CellType> CellType::vectorOfHarborEnumValues;

/*static*/ const std::vector<CellType::Enum_CellType> &CellType::getVectorOfPossibleEnumValues()
{
	if (vectorOfPossibleEnumValues.empty())
	{
		vectorOfPossibleEnumValues.push_back(DESERT_TYPE);
		vectorOfPossibleEnumValues.push_back(FOREST_TYPE);
		vectorOfPossibleEnumValues.push_back(PASTURE_TYPE);
		vectorOfPossibleEnumValues.push_back(FIELDS_TYPE);
		vectorOfPossibleEnumValues.push_back(HILLS_TYPE);
		vectorOfPossibleEnumValues.push_back(MOUNTAINS_TYPE);
		vectorOfPossibleEnumValues.push_back(OPEN_SEA_TYPE);
		vectorOfPossibleEnumValues.push_back(GENERAL_HARBOR_TYPE);
		vectorOfPossibleEnumValues.push_back(WOOD_HARBOR_TYPE);
		vectorOfPossibleEnumValues.push_back(SHEEP_HARBOR_TYPE);
		vectorOfPossibleEnumValues.push_back(WHEAT_HARBOR_TYPE);
		vectorOfPossibleEnumValues.push_back(BRICK_HARBOR_TYPE);
		vectorOfPossibleEnumValues.push_back(ORE_HARBOR_TYPE);
	}
	return vectorOfPossibleEnumValues;
}

/*static*/ const std::vector<CellType::Enum_CellType> &CellType::getVectorOfLandEnumValues()
{
	if (vectorOfLandEnumValues.empty())
	{
		for (int i=0; i<4; ++i) vectorOfLandEnumValues.push_back(FOREST_TYPE);
		for (int i=0; i<4; ++i) vectorOfLandEnumValues.push_back(PASTURE_TYPE);
		for (int i=0; i<4; ++i) vectorOfLandEnumValues.push_back(FIELDS_TYPE);
		for (int i=0; i<3; ++i) vectorOfLandEnumValues.push_back(HILLS_TYPE);
		for (int i=0; i<3; ++i) vectorOfLandEnumValues.push_back(MOUNTAINS_TYPE);
		vectorOfLandEnumValues.push_back(DESERT_TYPE);
	}
	return vectorOfLandEnumValues;
}

/*static*/ const std::vector<CellType::Enum_CellType> &CellType::getVectorOfHarborEnumValues()
{
	if (vectorOfHarborEnumValues.empty())
	{
		for (int i=0; i<4; ++i) vectorOfHarborEnumValues.push_back(GENERAL_HARBOR_TYPE);
		vectorOfHarborEnumValues.push_back(WOOD_HARBOR_TYPE);
		vectorOfHarborEnumValues.push_back(SHEEP_HARBOR_TYPE);
		vectorOfHarborEnumValues.push_back(WHEAT_HARBOR_TYPE);
		vectorOfHarborEnumValues.push_back(BRICK_HARBOR_TYPE);
		vectorOfHarborEnumValues.push_back(ORE_HARBOR_TYPE);
	}
	return vectorOfHarborEnumValues;
}

/*static*/ bool CellType::canInit(Enum_CellType enumCellType)
{
	const std::vector<CellType::Enum_CellType> enumValues = CellType::getVectorOfPossibleEnumValues();
	for (std::vector<CellType::Enum_CellType>::const_iterator enumValueIterator = enumValues.begin(); enumValueIterator != enumValues.end(); ++enumValueIterator)
	{
		if (enumCellType == *enumValueIterator)
		{
			return true;
		}
	}
	return false;
}

/*explicit*/ CellType::CellType(Enum_CellType enumCellType): enumCellType(enumCellType)
{
	if (!CellType::canInit(enumCellType))
	{
		throw CatanClassContractException(__FILE__, __LINE__, "CellType::canInit(...) with constructor arguments should be true before creating instance.");
	}
}

CellType::Enum_CellType CellType::getEnum() const
{
	return enumCellType;
}

bool CellType::operator==(const CellType &other) const
{
	return enumCellType == other.enumCellType;
}

bool CellType::operator<(const CellType &other) const
{
	return enumCellType < other.enumCellType;
}

CellType& CellType::operator=(const CellType& other)
{
    if (this != &other)
    {
        enumCellType = other.enumCellType;
    }
    return *this;	
}

}